package com.geek.water.controller;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.geek.water.constant.CodeConstant;
import com.geek.water.constant.MessageConstant;
import com.geek.water.entity.Bill;
import com.geek.water.entity.BillDetail;
import com.geek.water.exception.WaterException;
import com.geek.water.result.Result;
import com.geek.water.service.BillService;
import com.geek.water.vo.BillQueryVO;
import com.geek.water.vo.BillVO;
import com.geek.water.vo.BillDetailVO;
import com.geek.water.vo.PageQueryVO;
import io.swagger.annotations.*;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.time.LocalDate;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
@RequestMapping("/admin/bill")
@RequiredArgsConstructor
@Api(tags = "后台系统-账单管理")
public class BillController {

    private final BillService billService;

    @ApiOperation("创建新账单")
    @PostMapping
    public Result createBill(@RequestBody @Valid BillVO billVO) {
        try {
            Bill created = billService.createBill(billVO);
            return new Result(CodeConstant.SUCCESS,
                    MessageConstant.GENERATE_BILL_SUCCESS,
                    created);
        } catch (WaterException e) {
            return new Result(CodeConstant.FAIL, e.getMessage());
        }
    }

    @ApiOperation("根据设备抄表数据生成账单")
    @PostMapping("/generate")
    public Result generateBillFromDevices(@RequestBody Map<String, Object> requestBody) {
        try {
            Long customerId = Long.valueOf(requestBody.get("customerId").toString());
            String billingPeriod = requestBody.get("billingPeriod").toString();

            Bill bill = billService.generateBillFromDeviceReadings(customerId, billingPeriod);
            return new Result(CodeConstant.SUCCESS, "账单生成成功", bill);
        } catch (WaterException e) {
            return new Result(CodeConstant.FAIL, e.getMessage());
        } catch (Exception e) {
            log.error("生成账单失败", e);
            return new Result(CodeConstant.FAIL, "生成账单失败: " + e.getMessage());
        }
    }

    @ApiOperation("计算设备用水量和费用")
    @GetMapping("/device/{deviceId}/usage")
    public Result calculateDeviceUsage(
            @PathVariable Long deviceId,
            @RequestParam String billingPeriod) {
        try {
            BillDetail detail = billService.calculateDeviceUsage(deviceId, billingPeriod);
            return new Result(CodeConstant.SUCCESS, "计算成功", detail);
        } catch (WaterException e) {
            return new Result(CodeConstant.FAIL, e.getMessage());
        } catch (Exception e) {
            log.error("计算设备用水量失败", e);
            return new Result(CodeConstant.FAIL, "计算失败: " + e.getMessage());
        }
    }

    @ApiOperation("获取客户设备计费信息")
    @GetMapping("/customer/{customerId}/billing")
    public Result getCustomerBilling(
            @PathVariable Long customerId,
            @RequestParam String billingPeriod) {
        try {
            List<BillDetail> billingDetails = billService.getCustomerDeviceBilling(customerId, billingPeriod);
            return new Result(CodeConstant.SUCCESS, "获取计费信息成功", billingDetails);
        } catch (Exception e) {
            log.error("获取客户计费信息失败", e);
            return new Result(CodeConstant.FAIL, "获取计费信息失败: " + e.getMessage());
        }
    }

    @ApiOperation("分页查询账单列表")
    @GetMapping("/page")
    public Result listBills(
            @RequestParam(value = "currentPage", defaultValue = "1") Integer currentPage,
            @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize,
            @RequestParam(value = "customerId", required = false) Long customerId,
            @RequestParam(value = "status", required = false) String status,
            @RequestParam(value = "startDate", required = false)
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate startDate,
            @RequestParam(value = "endDate", required = false)
            @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate endDate
    ) {
        try {
            PageQueryVO pageQuery = new PageQueryVO();
            pageQuery.setCurrentPage(currentPage);
            pageQuery.setPageSize(pageSize);

            BillQueryVO billQuery = new BillQueryVO();
            billQuery.setCustomerId(customerId);
            if (status != null && !status.isEmpty()) {
                billQuery.setStatus(Collections.singletonList(status));
            }
            billQuery.setStartDate(startDate);
            billQuery.setEndDate(endDate);

            Page<BillVO> page = billService.listBills(pageQuery, billQuery);
            return new Result(CodeConstant.SUCCESS,
                    MessageConstant.QUERY_BILL_SUCCESS,
                    page);
        } catch (Exception e) {
            log.error("查询账单列表失败", e);
            return new Result(CodeConstant.FAIL,
                    MessageConstant.QUERY_BILL_FAIL + ": " + e.getMessage());
        }
    }

    @ApiOperation("更新账单状态")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id",    value = "账单ID",  required = true,
                    paramType = "path", dataType = "long"),
            @ApiImplicitParam(name = "status",value = "账单状态",
                    required = true,
                    allowableValues = "unpaid,paid,overdue,refunded",
                    paramType = "query", dataType = "string")
    })
    @PostMapping("/{id}/status")
    public Result updateBillStatus(@PathVariable Long id,
                                   @RequestParam String status) {
        if (!Arrays.asList("unpaid","paid","overdue","refunded")
                .contains(status)) {
            return new Result(CodeConstant.FAIL,
                    MessageConstant.PARAM_INVALID);
        }
        try {
            billService.updateBillStatus(id, status);
            return new Result(CodeConstant.SUCCESS,
                    MessageConstant.SUCCESS);
        } catch (WaterException e) {
            return new Result(CodeConstant.FAIL, e.getMessage());
        }
    }

    @ApiOperation("根据账单编号查找账单")
    @GetMapping("/byCode")
    public Result findByBillCode(@RequestParam String billCode) {
        try {
            Bill bill = billService.findByBillCode(billCode);
            if (bill == null) {
                return new Result(CodeConstant.FAIL, "账单不存在");
            }
            return new Result(CodeConstant.SUCCESS, "查询成功", bill);
        } catch (Exception e) {
            return new Result(CodeConstant.FAIL, "查询失败: " + e.getMessage());
        }
    }

    @ApiOperation("根据账单ID获取账单详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "账单ID", required = true,
                    paramType = "path", dataType = "long")
    })
    @GetMapping("/{id}/detail")
    public Result getBillDetailById(@PathVariable Long id) {
        try {
            BillDetailVO billDetail = billService.getBillDetailById(id);
            if (billDetail == null) {
                return new Result(CodeConstant.FAIL, "账单不存在");
            }
            return new Result(CodeConstant.SUCCESS, "获取账单详情成功", billDetail);
        } catch (Exception e) {
            log.error("获取账单详情失败，账单ID：{}", id, e);
            return new Result(CodeConstant.FAIL, "获取账单详情失败: " + e.getMessage());
        }
    }

    @ApiOperation("根据账单编号获取账单详情")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "billCode", value = "账单编号", required = true,
                    paramType = "query", dataType = "string")
    })
    @GetMapping("/detail/byCode")
    public Result getBillDetailByCode(@RequestParam String billCode) {
        try {
            BillDetailVO billDetail = billService.getBillDetailByCode(billCode);
            if (billDetail == null) {
                return new Result(CodeConstant.FAIL, "账单不存在");
            }
            return new Result(CodeConstant.SUCCESS, "获取账单详情成功", billDetail);
        } catch (Exception e) {
            log.error("获取账单详情失败，账单编号：{}", billCode, e);
            return new Result(CodeConstant.FAIL, "获取账单详情失败: " + e.getMessage());
        }
    }

    @ApiOperation("修复账单开票状态")
    @PostMapping("/fixInvoiceStatus")
    public Result fixInvoiceStatus(@RequestParam String billCode) {
        try {
            Bill bill = billService.findByBillCode(billCode);
            if (bill == null) {
                return new Result(CodeConstant.FAIL, "账单不存在");
            }

            // 重置开票状态为未开票
            bill.setInvoiced(0);
            billService.updateById(bill);

            log.info("已修复账单 {} 的开票状态，重置为未开票", billCode);
            return new Result(CodeConstant.SUCCESS, "账单开票状态已重置为未开票");
        } catch (Exception e) {
            log.error("修复账单开票状态失败，账单编号：{}", billCode, e);
            return new Result(CodeConstant.FAIL, "修复失败: " + e.getMessage());
        }
    }

    @ApiOperation("手动删除账单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "id", value = "账单ID", required = true,
                    paramType = "path", dataType = "long")
    })
    @DeleteMapping("/{id}")
    public Result deleteBill(@PathVariable Long id) {
        try {
            boolean result = billService.deleteBillManually(id);
            if (result) {
                return new Result(CodeConstant.SUCCESS, "账单删除成功");
            } else {
                return new Result(CodeConstant.FAIL, "账单删除失败");
            }
        } catch (WaterException e) {
            return new Result(CodeConstant.FAIL, e.getMessage());
        } catch (Exception e) {
            log.error("删除账单失败，账单ID：{}", id, e);
            return new Result(CodeConstant.FAIL, "删除失败: " + e.getMessage());
        }
    }

    @ApiOperation("批量删除账单")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "billIds", value = "账单ID列表", required = true,
                    paramType = "body", dataType = "List")
    })
    @DeleteMapping("/batch")
    public Result deleteBillsBatch(@RequestBody List<Long> billIds) {
        try {
            boolean result = billService.deleteBillsBatch(billIds);
            if (result) {
                return new Result(CodeConstant.SUCCESS, "批量删除账单成功");
            } else {
                return new Result(CodeConstant.FAIL, "批量删除账单失败");
            }
        } catch (WaterException e) {
            return new Result(CodeConstant.FAIL, e.getMessage());
        } catch (Exception e) {
            log.error("批量删除账单失败，账单ID：{}", billIds, e);
            return new Result(CodeConstant.FAIL, "批量删除失败: " + e.getMessage());
        }
    }
}
